package com.study.springbootsecurity.util;

import com.aliyun.auth.credentials.Credential;
import com.aliyun.auth.credentials.provider.StaticCredentialProvider;
import com.aliyun.sdk.service.dysmsapi20170525.AsyncClient;
import com.aliyun.sdk.service.dysmsapi20170525.models.QuerySendDetailsRequest;
import com.aliyun.sdk.service.dysmsapi20170525.models.QuerySendDetailsResponse;
import com.aliyun.sdk.service.dysmsapi20170525.models.SendSmsRequest;
import com.aliyun.sdk.service.dysmsapi20170525.models.SendSmsResponse;
import com.google.gson.Gson;
import com.study.springbootsecurity.config.properties.AliyunSmsProperties;
import com.study.springbootsecurity.domain.dto.query.SendStatisticsQueryDTO;
import com.study.springbootsecurity.exception.BusinessException;
import darabonba.core.client.ClientOverrideConfiguration;
import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static com.baomidou.mybatisplus.extension.ddl.DdlScriptErrorHandler.PrintlnLogErrorHandler.log;

/**
 * @Description: TODO
 * @author: Huangjianyun
 * @date: 2025-06-13 17:13
 */

public class SmsUtil {
    private final AliyunSmsProperties smsProperties;
    private static final String TEMPLATE_CODE = "code";
    private AsyncClient asyncClient;

    public SmsUtil(AliyunSmsProperties smsProperties, SmsClientFactory factory) {
        this.smsProperties = smsProperties;
        this.asyncClient = factory.getAsyncClient();
    }

    public SmsUtil() {
        // new初始化对象，其实没有用到这个参数
        this.smsProperties = new AliyunSmsProperties();
    }

    /**
     * 发送验证码
     *
     * @param phone 手机号
     * @param code  验证码
     * @return SendSmsResponse 验证码响应结果
     */
    public SendSmsResponse sendSms(String phone, String code) {
        Map<String, String> params = new HashMap<>();
        params.put(TEMPLATE_CODE, code);
        String templateParam = GsonUtils.toJSONString(params);

        SendSmsRequest sendSmsRequest = SendSmsRequest.builder()
                .signName(smsProperties.getSignName())
                .templateCode(smsProperties.getTemplateCode())
                .phoneNumbers(phone)
                .templateParam(templateParam)
                .build();

        CompletableFuture<SendSmsResponse> response = asyncClient.sendSms(sendSmsRequest);
        try {
            // 创建map 存放key: code  value: 验证码参数 {"code":code}
            SendSmsResponse resp = response.get();
            System.out.println(new Gson().toJson(resp));
            return resp;
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            log.error("发送短信被中断", e);
            throw new BusinessException("发送短信被中断", e);
        } catch (ExecutionException e) {
            log.error("发送短信执行异常", e);
            throw new BusinessException("发送短信异常", e);
        } catch (Exception e) {
            log.error("发送短信未知异常", e);
            throw new BusinessException("发送短信失败", e);
        }
    }


    /**
     * 从固定格式的短信中提取6位验证码
     * 适用于类似 "验证码为：123456" 或 "您的验证码是123456，有效期..." 的格式
     *
     * @param content
     * @return String 提取验证码字符串
     */
    public String extractCodeFromContent(String content) {
        if (content == null || content.isEmpty()) {
            return null;
        }

        // 匹配 验证码为 中文冒号或者英文冒号 后面的6位数字
        // Pattern pattern = Pattern.compile("验证码为[：:]?\\s*(\\d{4}|\\d{6})");
        Pattern pattern = Pattern.compile("验证码是[：:]?\\s*(\\d{6}|\\d{4})");
        Matcher matcher = pattern.matcher(content);

        if (matcher.find()) {
            // 获取括号内的捕获组
            return matcher.group(1);
        }
        return "";
    }


    // 校验发送验证码接口参数和返回第三方验证码content的验证码
    public boolean validSmsCode(String code, String codeFromContent) {
        // 参数校验
        if (StringUtils.isBlank(code)) {
            log.warn("用户输入的验证码为空");
            throw new BusinessException("验证码不能为空");
        }

        if (StringUtils.isBlank(codeFromContent)) {
            log.error("content提取验证码不能为null");
            throw new BusinessException("content提取验证码不能为null");
        }
        if (!isValidSmsCodeFormat(codeFromContent)) {
            log.error("content提取验证码必须6为数字字符串");
            throw new BusinessException("content提取验证码必须6为数字字符串");
        }
        if (!code.equalsIgnoreCase(codeFromContent)) {
            log.error("验证码参数和content提取验证码参数不一致");
            throw new BusinessException("验证码参数和content提取验证码参数不一致");
        }
        return true;
    }

    /**
     * 检查验证码是否符合格式要求
     *
     * @param code 验证码
     * @return 是否符合格式
     */
    private boolean isValidSmsCodeFormat(String code) {
        // 检查是否为6位数字
        return code != null && code.matches("^\\d{6}$");
    }

    /**
     * 获取短信详情内容
     *
     * @param queryDTO 查询验证码详情参数
     * @return 是否符合格式
     */
    public QuerySendDetailsResponse querySendDetails(SendStatisticsQueryDTO queryDTO) {
        // Parameter settings for API request
        QuerySendDetailsRequest querySendDetailsRequest = QuerySendDetailsRequest.builder()
                .phoneNumber(queryDTO.getPhoneNumber())
                .bizId(queryDTO.getBizId())
                .sendDate(queryDTO.getSendDate())
                .pageSize(queryDTO.getPageSize())
                .currentPage(queryDTO.getCurrentPage())
                .build();

        CompletableFuture<QuerySendDetailsResponse> response = asyncClient.querySendDetails(querySendDetailsRequest);
        QuerySendDetailsResponse resp;
        try {
            resp = response.get();
            System.out.println(new Gson().toJson(resp));
            return resp;
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            log.error("获取短信详情被中断", e);
            throw new BusinessException("获取短信详情被中断", e);
        } catch (ExecutionException e) {
            log.error("获取短信详情执行异常", e);
            throw new BusinessException("获取短信详情异常", e);
        } catch (Exception e) {
            log.error("获取短信详情未知异常", e);
            throw new BusinessException("获取短信详情失败", e);
        }
    }
}
